{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "296c4ed2-43a5-45b2-8d95-9f8d92294fbb",
   "metadata": {},
   "source": [
    "# Knowledge Graphs for RAG\n",
    "https://www.deeplearning.ai/short-courses/knowledge-graphs-rag/"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7df06187-5ce3-47b8-9acd-26fbefc78d62",
   "metadata": {},
   "source": [
    "## 本地启动Neo4j\n",
    "\n",
    "https://medium.com/@matthewghannoum/simple-graph-database-setup-with-neo4j-and-docker-compose-061253593b5a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b4e851fc-6e7c-413b-b288-51e09e18bed0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting neo4j\n",
      "  Downloading neo4j-5.20.0.tar.gz (202 kB)\n",
      "\u001b[2K     \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m203.0/203.0 kB\u001b[0m \u001b[31m8.3 kB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m kB/s\u001b[0m eta \u001b[36m0:00:02\u001b[0m:07\u001b[0m\n",
      "\u001b[?25h  Installing build dependencies ... \u001b[?25ldone\n",
      "\u001b[?25h  Getting requirements to build wheel ... \u001b[?25ldone\n",
      "\u001b[?25h  Installing backend dependencies ... \u001b[?25ldone\n",
      "\u001b[?25h  Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n",
      "\u001b[?25hRequirement already satisfied: pytz in /Users/laobao/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages (from neo4j) (2024.1)\n",
      "Building wheels for collected packages: neo4j\n",
      "  Building wheel for neo4j (pyproject.toml) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for neo4j: filename=neo4j-5.20.0-py3-none-any.whl size=280771 sha256=fc97ad2935485d3d084c30fcccbea9c8c0a820996a5c4dd40a09a71c2bec34cc\n",
      "  Stored in directory: /Users/laobao/Library/Caches/pip/wheels/cb/12/66/764554d079caad4b9a11a02cfc0d200dd876d12935b9cf7e64\n",
      "Successfully built neo4j\n",
      "Installing collected packages: neo4j\n",
      "Successfully installed neo4j-5.20.0\n"
     ]
    }
   ],
   "source": [
    "!pip install neo4j"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3feefca8-d325-440c-a634-c9ba3bf8c335",
   "metadata": {},
   "source": [
    "## 设置环境"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "149a8a2e-f932-4615-b13d-d17081ec0e86",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "import os\n",
    "\n",
    "from langchain_community.graphs import Neo4jGraph\n",
    "\n",
    "# Warning control\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "7ecade52-a73f-4a14-8ee9-5fa473054deb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "neo4j://localhost:7687\n"
     ]
    }
   ],
   "source": [
    "load_dotenv(\".env.local\",override=True)\n",
    "NEO4J_URI = os.getenv(\"NEO4J_URI\")\n",
    "NEO4J_USERNAME = os.getenv(\"NEO4J_USERNAME\")\n",
    "NEO4J_PASSWORD = os.getenv(\"NEO4J_PASSWORD\")\n",
    "NEO4J_DATABASE = os.getenv(\"NEO4J_DATABASE\")\n",
    "\n",
    "\n",
    "print(NEO4J_URI)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "9a2ae8d0-caba-484c-8230-4d1e9ca00c83",
   "metadata": {},
   "outputs": [],
   "source": [
    "kg = Neo4jGraph(\n",
    "    url=NEO4J_URI,\n",
    "    username=NEO4J_USERNAME,\n",
    "    password=NEO4J_PASSWORD,\n",
    "    database=NEO4J_DATABASE)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32e09c89-67ee-422c-aa6d-f682e5583da6",
   "metadata": {},
   "source": [
    "## 导入测试数据：Movies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "f9d813ac-109a-40f7-8b60-1ec1085487a6",
   "metadata": {},
   "outputs": [],
   "source": [
    "cypher = \"\"\"\n",
    "    MATCH (n:Movie)\n",
    "    RETURN n.tagline LIMIT 10\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "92c76929-51bb-4d0d-a1be-beb17f88fc45",
   "metadata": {},
   "outputs": [],
   "source": [
    "result = kg.query(cypher)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "4e215064-3eca-459e-b81b-1b1281a91059",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'n.tagline': 'Welcome to the Real World'},\n",
       " {'n.tagline': 'Free your mind'},\n",
       " {'n.tagline': 'Everything that has a beginning has an end'},\n",
       " {'n.tagline': 'Evil has its winning ways'},\n",
       " {'n.tagline': \"In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth.\"},\n",
       " {'n.tagline': 'I feel the need, the need for speed.'},\n",
       " {'n.tagline': 'The rest of his life begins now.'},\n",
       " {'n.tagline': \"For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of.\"},\n",
       " {'n.tagline': 'A comedy from the heart that goes for the throat.'},\n",
       " {'n.tagline': 'After life there is more. The end is just the beginning.'}]"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "01243372-d58e-4e98-afd7-539cf74edf16",
   "metadata": {},
   "outputs": [],
   "source": [
    "cypher = \"\"\"\n",
    "    MATCH (tom:Person {name:\"Tom Hanks\"})\n",
    "    RETURN tom.name as TOM\n",
    "    \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "2b0fc181-a760-442e-93cc-0f96913f46af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'TOM': 'Tom Hanks'}]"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = kg.query(cypher)\n",
    "result"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "98be70c2-fe9d-47ff-889d-0445c3914e14",
   "metadata": {},
   "source": [
    "## 创建索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "0c4f90f8-ab3d-48f4-a95d-d9fdcd6dfc67",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cypher = \"\"\"\n",
    "    CREATE VECTOR INDEX movie_tagline_embeddings IF NOT EXISTS\n",
    "    FOR (m:Movie) ON (m.taglineEmbedding)\n",
    "    OPTIONS {\n",
    "        indexConfig: {\n",
    "            `vector.dimensions`: 1536,\n",
    "            `vector.similarity_function`: 'cosine'\n",
    "    }}\n",
    "\"\"\"\n",
    "kg.query(cypher)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "70dc1716-d840-41bd-aa5c-c6469a5b5ded",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'id': 3,\n",
       "  'name': 'movie_tagline_embeddings',\n",
       "  'state': 'ONLINE',\n",
       "  'populationPercent': 100.0,\n",
       "  'type': 'VECTOR',\n",
       "  'entityType': 'NODE',\n",
       "  'labelsOrTypes': ['Movie'],\n",
       "  'properties': ['taglineEmbedding'],\n",
       "  'indexProvider': 'vector-2.0',\n",
       "  'owningConstraint': None,\n",
       "  'lastRead': None,\n",
       "  'readCount': 0}]"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kg.query(\"\"\"\n",
    "    SHOW VECTOR INDEXES\n",
    "    \"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03b42c6d-5c14-4f3e-b2b2-d04ac297bba8",
   "metadata": {},
   "source": [
    "## 填充数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "2994b1cb-7b32-44b9-b0e6-683eb18f3fe9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'https://api.openai.com/v1/embeddings'"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')\n",
    "\n",
    "# Note the code below is unique to this course environment, and not a \n",
    "# standard part of Neo4j's integration with OpenAI. Remove if running \n",
    "# in your own environment.\n",
    "OPENAI_ENDPOINT = os.getenv('OPENAI_BASE_URL') + '/embeddings'\n",
    "\n",
    "OPENAI_ENDPOINT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "28803451-fa08-4081-b4e5-a5f9d368b810",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Generated Cypher Statement is not valid\n{code: Neo.ClientError.Statement.SyntaxError} {message: Unknown function 'genai.vector.encode' (line 3, column 21 (offset: 73))\n\"    WITH movie, genai.vector.encode(\"\n                 ^}",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mCypherSyntaxError\u001b[0m                         Traceback (most recent call last)",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/langchain_community/graphs/neo4j_graph.py:506\u001b[0m, in \u001b[0;36mNeo4jGraph.query\u001b[0;34m(self, query, params)\u001b[0m\n\u001b[1;32m    505\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 506\u001b[0m     data \u001b[38;5;241m=\u001b[39m \u001b[43msession\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mQuery\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtext\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mquery\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    507\u001b[0m     json_data \u001b[38;5;241m=\u001b[39m [r\u001b[38;5;241m.\u001b[39mdata() \u001b[38;5;28;01mfor\u001b[39;00m r \u001b[38;5;129;01min\u001b[39;00m data]\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/neo4j/_sync/work/session.py:313\u001b[0m, in \u001b[0;36mSession.run\u001b[0;34m(self, query, parameters, **kwargs)\u001b[0m\n\u001b[1;32m    312\u001b[0m parameters \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mdict\u001b[39m(parameters \u001b[38;5;129;01mor\u001b[39;00m {}, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m--> 313\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_auto_result\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    314\u001b[0m \u001b[43m    \u001b[49m\u001b[43mquery\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mparameters\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_config\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdatabase\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    315\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_config\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mimpersonated_user\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_config\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdefault_access_mode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    316\u001b[0m \u001b[43m    \u001b[49m\u001b[43mbookmarks\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_config\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnotifications_min_severity\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    317\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_config\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnotifications_disabled_categories\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    318\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    320\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_auto_result\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/neo4j/_sync/work/result.py:181\u001b[0m, in \u001b[0;36mResult._run\u001b[0;34m(self, query, parameters, db, imp_user, access_mode, bookmarks, notifications_min_severity, notifications_disabled_categories)\u001b[0m\n\u001b[1;32m    180\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_connection\u001b[38;5;241m.\u001b[39msend_all()\n\u001b[0;32m--> 181\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_attach\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/neo4j/_sync/work/result.py:301\u001b[0m, in \u001b[0;36mResult._attach\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    300\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_attached \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[0;32m--> 301\u001b[0m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_connection\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfetch_message\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/neo4j/_sync/io/_common.py:178\u001b[0m, in \u001b[0;36mConnectionErrorHandler.__getattr__.<locals>.outer.<locals>.inner\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m    177\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 178\u001b[0m     \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    179\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (Neo4jError, ServiceUnavailable, SessionExpired) \u001b[38;5;28;01mas\u001b[39;00m exc:\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/neo4j/_sync/io/_bolt.py:850\u001b[0m, in \u001b[0;36mBolt.fetch_message\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    847\u001b[0m tag, fields \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minbox\u001b[38;5;241m.\u001b[39mpop(\n\u001b[1;32m    848\u001b[0m     hydration_hooks\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mresponses[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mhydration_hooks\n\u001b[1;32m    849\u001b[0m )\n\u001b[0;32m--> 850\u001b[0m res \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_process_message\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtag\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfields\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    851\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39midle_since \u001b[38;5;241m=\u001b[39m monotonic()\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/neo4j/_sync/io/_bolt5.py:369\u001b[0m, in \u001b[0;36mBolt5x0._process_message\u001b[0;34m(self, tag, fields)\u001b[0m\n\u001b[1;32m    368\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 369\u001b[0m     \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mon_failure\u001b[49m\u001b[43m(\u001b[49m\u001b[43msummary_metadata\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    370\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (ServiceUnavailable, DatabaseUnavailable):\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/neo4j/_sync/io/_common.py:245\u001b[0m, in \u001b[0;36mResponse.on_failure\u001b[0;34m(self, metadata)\u001b[0m\n\u001b[1;32m    244\u001b[0m Util\u001b[38;5;241m.\u001b[39mcallback(handler)\n\u001b[0;32m--> 245\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m Neo4jError\u001b[38;5;241m.\u001b[39mhydrate(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mmetadata)\n",
      "\u001b[0;31mCypherSyntaxError\u001b[0m: {code: Neo.ClientError.Statement.SyntaxError} {message: Unknown function 'genai.vector.encode' (line 3, column 21 (offset: 73))\n\"    WITH movie, genai.vector.encode(\"\n                 ^}",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[106], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mkg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mquery\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\"\"\u001b[39;49m\n\u001b[1;32m      2\u001b[0m \u001b[38;5;124;43m    MATCH (movie:Movie) WHERE movie.tagline IS NOT NULL\u001b[39;49m\n\u001b[1;32m      3\u001b[0m \u001b[38;5;124;43m    WITH movie, genai.vector.encode(\u001b[39;49m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;124;43m        movie.tagline, \u001b[39;49m\n\u001b[1;32m      5\u001b[0m \u001b[38;5;124;43m        \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mOpenAI\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\n\u001b[1;32m      6\u001b[0m \u001b[38;5;124;43m        \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\n\u001b[1;32m      7\u001b[0m \u001b[38;5;124;43m          token: $openAiApiKey,\u001b[39;49m\n\u001b[1;32m      8\u001b[0m \u001b[38;5;124;43m          endpoint: $openAiEndpoint\u001b[39;49m\n\u001b[1;32m      9\u001b[0m \u001b[38;5;124;43m        }) AS vector\u001b[39;49m\n\u001b[1;32m     10\u001b[0m \u001b[38;5;124;43m    CALL db.create.setNodeVectorProperty(movie, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtaglineEmbedding\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, vector)\u001b[39;49m\n\u001b[1;32m     11\u001b[0m \u001b[38;5;124;43m    \u001b[39;49m\u001b[38;5;124;43m\"\"\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m     12\u001b[0m \u001b[43m    \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mopenAiApiKey\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43mOPENAI_API_KEY\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mopenAiEndpoint\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mOPENAI_ENDPOINT\u001b[49m\u001b[43m}\u001b[49m\n\u001b[1;32m     13\u001b[0m \u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/opt/anaconda3/envs/llama-index/lib/python3.10/site-packages/langchain_community/graphs/neo4j_graph.py:512\u001b[0m, in \u001b[0;36mNeo4jGraph.query\u001b[0;34m(self, query, params)\u001b[0m\n\u001b[1;32m    510\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m json_data\n\u001b[1;32m    511\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m CypherSyntaxError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m--> 512\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGenerated Cypher Statement is not valid\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
      "\u001b[0;31mValueError\u001b[0m: Generated Cypher Statement is not valid\n{code: Neo.ClientError.Statement.SyntaxError} {message: Unknown function 'genai.vector.encode' (line 3, column 21 (offset: 73))\n\"    WITH movie, genai.vector.encode(\"\n                 ^}"
     ]
    }
   ],
   "source": [
    "kg.query(\"\"\"\n",
    "    MATCH (movie:Movie) WHERE movie.tagline IS NOT NULL\n",
    "    WITH movie, genai.vector.encode(\n",
    "        movie.tagline, \n",
    "        \"OpenAI\", \n",
    "        {\n",
    "          token: $openAiApiKey,\n",
    "          endpoint: $openAiEndpoint\n",
    "        }) AS vector\n",
    "    CALL db.create.setNodeVectorProperty(movie, \"taglineEmbedding\", vector)\n",
    "    \"\"\", \n",
    "    params={\"openAiApiKey\":OPENAI_API_KEY, \"openAiEndpoint\": OPENAI_ENDPOINT}\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "39d9fbd5-7980-4a0c-992f-470022c8096c",
   "metadata": {},
   "outputs": [],
   "source": [
    "result = kg.query(\"\"\"\n",
    "    MATCH (m:Movie) \n",
    "    WHERE m.tagline IS NOT NULL\n",
    "    RETURN m.tagline, m.taglineEmbedding\n",
    "    LIMIT 1\n",
    "    \"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "826f9597-428e-440a-b523-ff5f4465dcab",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Welcome to the Real World'"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result[0]['m.tagline']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "cc6acdf2-9656-4ab9-a217-6d7ab8644896",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "object of type 'NoneType' has no len()",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[102], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mresult\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mm.taglineEmbedding\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[0;31mTypeError\u001b[0m: object of type 'NoneType' has no len()"
     ]
    }
   ],
   "source": [
    "len(result[0]['m.taglineEmbedding'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b84f6695-6f75-4111-a669-b54bbf0d5919",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
